using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using TheLogWatcher.Properties;
using System.Collections.Specialized;
using System.ComponentModel;

namespace TheLogWatcher
{
    public class DataAccess
    {
        public enum FileHandling
        {
            SingleFileHandling = 0,
            MultiFileHandling = 1
        }

        public enum DataHandling
        {
            DataBuffering = 0,
            LineIndexing = 1
        }

        public enum ReaderHandling
        {
            ReadFull = 0,
            ActiveTypes = 1,
            ActiveRows = 2
        }

        private FileHandling fileHandle;

        /// <summary>
        ///     <u>Performance Setting: </u>
        ///     Specifies the variant in handling log file.
        /// </summary>
        public FileHandling FileHandle
        {
            get { return fileHandle; }
            set { fileHandle = value; }
        }

        private DataHandling dataHandle;

        /// <summary>
        ///     <u>Performance Setting: </u>
        ///     Specifies the variant in managing data when
        ///     reading into memory.
        /// </summary>
        public DataHandling DataHandle
        {
            get { return dataHandle; }
            set { dataHandle = value; }
        }

        private ReaderHandling readerHandle;

        /// <summary>
        ///     <u>Performance Setting: </u>
        ///     Specifies the variant in reading data when
        ///     necessary for GUI.
        /// </summary>
        public ReaderHandling ReaderHandle
        {
            get { return readerHandle; }
            set { readerHandle = value; }
        }

        /// <summary>
        ///     It represents all currently active
        ///     message types selected in GUI.
        /// </summary>
        public List<MessageTypes> SelectedTypes
        {
            get 
            {
                StringCollection strgCol = Settings.Default.SelectedTypes;
                if (strgCol != null && strgCol.Count > 0)
                {
                    List<MessageTypes> outputList = new List<MessageTypes>(strgCol.Count);
                    foreach (string activatedType in strgCol)
                    {
                        outputList.Add(MessageType.GetMessageType(activatedType));
                    }
                    return outputList;
                }
                return null;
            }
        }

        /// <summary>
        ///     This is used when "Read Active Types" or "Read Active Rows"
        ///     options are enabled. It represents all currently active
        ///     message types selected in GUI.
        /// </summary>
        public string[] SelectedTypesAsString
        {
            get
            {
                StringCollection strgCol = Settings.Default.SelectedTypes;
                if (strgCol != null && strgCol.Count > 0)
                {
                    string[] outputArray = new string[strgCol.Count];
                    int i = 0;
                    foreach (string activatedType in strgCol)
                    {
                        outputArray[i] = activatedType;
                        i++;
                    }
                    return outputArray;
                }
                return null;
            }
        }

        private LogFileProvider fnProvider;

        /// <summary>
        ///     This object holds information about files used
        ///     in currently opened log file.
        /// </summary>
        public LogFileProvider FnProvider
        {
            get { return fnProvider; }
            set { fnProvider = value; }
        }

        private Dictionary<MessageTypes, List<IndexObject>> indicesByMessageType = new Dictionary<MessageTypes, List<IndexObject>>();
        public Dictionary<MessageTypes, List<IndexObject>> IndicesByMessageType
        {
            get { return indicesByMessageType; }
            //set { indicesByMessageType = value; }
        }

        private LinkedList<long> indicesByFileIndex = new LinkedList<long>();
        /// <summary>
        ///     A linked list of all file stream indices (sorted).
        /// </summary>
        public LinkedList<long> IndicesByFileIndex
        {
            get { return indicesByFileIndex; }
            //set { indicesByFileIndex = value; }
        }

        public void addIndex(IndexObject index)
        {
            if (index == null)
            {
                return;
            }
            this.indices.Add(index);
            UpdateIndexList(index);
        }

        public void addSortedIndex(IndexObject index)
        {
            if (index == null)
            {
                return;
            }
            this.sortedIndices.Add(index);
            UpdateIndexList(index);
        }

        private void UpdateIndexList(IndexObject index)
        {
            //Console.WriteLine("Added Index: " + index.FileIndex + "  <" + index.MessageType + ">");
            //
            if (!this.indicesByMessageType.ContainsKey(index.MessageType))
            {
                this.indicesByMessageType.Add(index.MessageType, new List<IndexObject>());
            }
            this.indicesByMessageType[index.MessageType].Add(index);
            //
            this.indicesByFileIndex.AddLast(index.FileIndex);
        }

        private List<IndexObject> indices = new List<IndexObject>();
        /// <summary>
        ///     A sorted list of all file indices.
        /// </summary>
        public List<IndexObject> Indices
        {
            get { return indices; }
            //set { indices = value; }
        }

        private List<IndexObject> sortedIndices = new List<IndexObject>();
        /// <summary>
        ///     A sorted list of the indices for all visible entries.
        /// </summary>
        public List<IndexObject> SortedIndices
        {
            get { return sortedIndices; }
            set { sortedIndices = value; }
        }

        private List<IndexObject> filteredIndices;
        /// <summary>
        ///     A sorted list of the indices for all visible entries.
        /// </summary>
        public List<IndexObject> FilteredIndices
        {
            get { return filteredIndices; }
            set { filteredIndices = value; }
        }

        /// <summary>
        ///     Sort and filter all available entries for selected types.
        /// </summary>
        public void SortListViewEntries()
        {
            this.SortedIndices.Clear();
            List<IndexObject> indices = this.Indices;
            if (this.FilteredIndices != null)
            {
                indices = this.FilteredIndices;
            }
            this.indicesByMessageType = new Dictionary<MessageTypes, List<IndexObject>>();
            foreach (IndexObject item in indices)
            {
                // TODO: implement sorting by date etc....
                if (this.SelectedTypes.Contains(item.MessageType))
                {
                    addSortedIndex(item);
                }
            }
        }

        private LogFile currentLogFile;

        /// <summary>
        ///     Represents the currently opened logfile. Is null if nothing opened.
        /// </summary>
        public LogFile CurrentLogFile
        {
            get { return currentLogFile; }
            set { currentLogFile = value; }
        }

        //private FormatSettings currentLogFormat;

        ///// <summary>
        /////     Represents the log format of the currently opened logfile.
        ///// </summary>
        //public FormatSettings CurrentLogFormat
        //{
        //    get { return currentLogFormat; }
        //    set { currentLogFormat = value; }
        //}

        private LogFormat currentLogFormat;

        /// <summary>
        ///     Represents the log format of the currently opened logfile.
        /// </summary>
        public LogFormat CurrentLogFormat
        {
            get { return currentLogFormat; }
            set { currentLogFormat = value; }
        }

        private DateTime dateFirstEntry = DateTime.MaxValue;
        public DateTime DateFirstEntry
        {
            get { return dateFirstEntry; }
            set { dateFirstEntry = value; }
        }

        private DateTime dateLastEntry = DateTime.MinValue;

        public DateTime DateLastEntry
        {
            get { return dateLastEntry; }
            set { dateLastEntry = value; }
        }
    }
}
